/**
 * @date 2006-3-29 14:37:19
 *
 */
package org.nanhill.xmlro;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;

/**
 * @author alin [xalinx at gmail dot com]
 * 
 */
public abstract class AbstractXmlroTransport implements XmlroTransport {
	/**
	 * Default transport character set.
	 */
	private static final String DEFAULT_CHAR_SET = "UTF-8";

	/**
	 * Transport character set.
	 */
	protected String characterSet = DEFAULT_CHAR_SET;

	public String getCharacterSet() {
		return characterSet;
	}

	/**
	 * Set transport character set.
	 * 
	 * @param charSet
	 */
	public void setCharacterSet(String charSet) {
		this.characterSet = charSet;
	}

	public Object receive(InputStream inputStream) throws XmlroException, IOException {
		return receive(null, inputStream);
	}

	public Object receive(String xml) throws XmlroException {
		return this.receive(null, xml);
	}

	public <E> E receive(E wrap, InputStream inputStream) throws XmlroException, IOException {
		return this.receive(wrap, this.getXml(inputStream));
	}

	public <E> E receive(E wrapObj, String xml) throws XmlroException {
		XmlroInput<E> input = getWrappedInput(wrapObj);
		input.setReader(new StringReader(xml));
		E product = input.echo();
		return product;
	}

	public <E> E receive(Class<E> wrapClz, String xml) throws XmlroException {
		XmlroInput<E> input = getWrappedInput(wrapClz);
		input.setReader(new StringReader(xml));
		E product = input.echo();
		return product;
	}

	public <E> E receive(Class<E> wrapClz, InputStream inputStream)
			throws XmlroException, IOException {
		return (E) this.receive(wrapClz, this.getXml(inputStream));
	}

	public void send(Object in, OutputStream outputStream)
			throws XmlroException, IOException {
		String out = this.send(in);
		try {
			outputStream.write(out.getBytes(characterSet));
			outputStream.flush();
		} catch (UnsupportedEncodingException e) {
			throw new XmlroException(e);
		} catch (IOException e) {
			throw new XmlroException(e);
		}
	}

	public String send(Object in) throws XmlroException {
		XmlroOutput output = this.getOutput();
		output.setParsed(in);
		output.construct();
		String product = output.getProduct().toString();
		return product;
	}

	public String getXml(InputStream inputStream) throws XmlroException,IOException {
		final String endFlag = this.getEndFlag();
		StringBuilder sb = new StringBuilder();
		BufferedReader in = new BufferedReader(new InputStreamReader(
				inputStream, characterSet));
		String str;
		while ((str = in.readLine()) != null) {
			sb.append(str);
			if (str.endsWith(endFlag)) {
				break;
			}
		}

		return sb.toString();
	}

	protected abstract String getEndFlag();

	/**
	 * Get xmlro ouput.
	 * 
	 * @return
	 */
	protected abstract XmlroOutput getOutput();

	/**
	 * Get generic xmlro input.
	 * 
	 * @return
	 */
	protected abstract XmlroInput getInput();

	/**
	 * Get specified export object xmlro input.
	 * 
	 * @return
	 */
	protected abstract <E> XmlroInput<E> getWrappedInput(E wrap);

	/**
	 * Get specified export object xmlro input.
	 * 
	 * @param <E>
	 * @param wrapClz
	 * @return
	 */
	protected abstract <E> XmlroInput<E> getWrappedInput(Class<E> wrapClz);

}
